/******************** (C) COPYRIGHT 2014 SONiX *******************************
* COMPANY:			SONiX
* DATE:					2014/01
* AUTHOR:				SA1
* IC:						SN32F288
* DESCRIPTION:	
*____________________________________________________________________________
* REVISION	Date				User		Description
*
*____________________________________________________________________________
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS TIME TO MARKET.
* SONiX SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL 
* DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE
* AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN 
* IN CONNECTION WITH THEIR PRODUCTS.
*****************************************************************************/

/*_____ I N C L U D E S ____________________________________________________*/
#include	"SN32F280.h"
#include	"SN32F200_Def.h"
#include	"ExFlash.h"
#include  "..\Driver\SPI.h"
#include  "..\Driver\Utility.h"
#include  "..\LED\LED_Driver.h"
#include  "..\KB\KB_Scan.h"
#include  "..\KB\KB_BT.h"
#include	"..\Usb\usbepfunc.h"
#include	"..\Usb\usbuser.h"

/*_____ D E C L A R A T I O N S ____________________________________________*/
uint8_t ExtFlash_MFID[2];
uint8_t ExtFlash_DataBuf[256];

/*_____ D E F I N I T I O N S ______________________________________________*/

/*_____ M A C R O S ________________________________________________________*/


/*_____ F U N C T I O N S __________________________________________________*/
/*****************************************************************************
* Function		: ExFlash_Init
* Description	: 
* Input			: None
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void ExFlash_Init(void)
{
	SPI1_Init();
}

/*****************************************************************************
* Function		: ExtFlash_RW_Byte
* Description	: 
* Input			: 
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
uint8_t ExtFlash_RW_Byte(uint8_t data)
{
	uint8_t miso_data;

	SN_SPI1->DATA = data;
	while(SN_SPI1->STAT_b.BUSY);

	miso_data = SN_SPI1->DATA;
	return miso_data;
}
/*****************************************************************************
* Function		: ExtFlash_Read_DevID
* Description	: 
* Input			: 
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void ExFlash_Read_DevID()
{
	FLASH_SEL_CLR;
	ExtFlash_RW_Byte(W25Qxx_READ_DEV_ID);
	ExtFlash_RW_Byte(0x00);
	ExtFlash_RW_Byte(0x00);
	ExtFlash_RW_Byte(0x00);

	ExtFlash_MFID[0] = ExtFlash_RW_Byte(0x00);
	ExtFlash_MFID[1] = ExtFlash_RW_Byte(0x00);
	
	FLASH_SEL_SET;
}
/*****************************************************************************
* Function		: ExtFlash_Set_Address
* Description	: 
* Input			: 
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void ExFlash_Set_Address(uint32_t addr)
{
	volatile uint8_t temp;
	SPI1_RW(0x03);
	SPI1_RW(((addr >> 16) & 0xFF));
	SPI1_RW(((addr >> 8) & 0xFF));
	SPI1_RW((addr & 0xFF));
	while(SN_SPI1->STAT_b.BUSY);
}
/*****************************************************************************
* Function		: ExtFlash_Read_Data
* Description	: 
* Input			: 
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void ExFlash_Read_Data(uint32_t addr, uint16_t len)
{
	uint32_t i;
	FLASH_SEL_CLR;
	ExFlash_Set_Address(addr);
	
	for(i = 0; i < len; i += 2)
	{
		ExtFlash_DataBuf[i] = ExtFlash_RW_Byte(i);
		ExtFlash_DataBuf[i + 1] = ExtFlash_RW_Byte(i + 1);
	}
	FLASH_SEL_SET;
}

/*****************************************************************************
* Function		: ExFlash_Sector_Erase
* Description	: 
* Input			: 
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void ExFlash_Sector_Erase(uint32_t addr)
{
	FLASH_SEL_CLR;
	ExtFlash_RW_Byte(0x06);						//Write Enable
	FLASH_SEL_SET;
	
	FLASH_SEL_CLR;
	ExtFlash_RW_Byte(0x20);
	ExtFlash_RW_Byte((addr >> 16) & 0xFF);
	ExtFlash_RW_Byte((addr >> 8) & 0xFF);
	ExtFlash_RW_Byte(addr & 0xFF);
	FLASH_SEL_SET;
}

/*****************************************************************************
* Function		: ExFLASH_4KWrite
* Description	: 
* Input			: None
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void ExFLASH_4KWrite(uint32_t addr,uint8_t *pData,uint32_t len)
{
	uint32_t i = 0;
	if((addr&0xFFF) == 0)
	{
		ExFlash_Sector_Erase(addr);					//Sector Erase
		ExFlash_WaitIdle();		
	}
	for(i=0;i<16;i++)
	{
		ExFlash_Write_Data(addr,pData+i*256,256);
		ExFlash_WaitIdle();	
		addr += 256;	
	}
}
/*****************************************************************************
* Function		: ExFLASH_4XWrite
* Description	: 
* Input			: None
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void ExFLASH_4XWrite(uint32_t addr,uint8_t *pData,uint32_t len)
{
	uint32_t i = 0;
	for(i=0;i<len/4;i++)
	{
		if((addr&0xFFF) == 0)
		{
			ExFlash_Sector_Erase(addr);					//Sector Erase
			ExFlash_WaitIdle();		
		}
		ExFlash_Write_Data(addr,pData+i*4,4);
		ExFlash_WaitIdle();	
		addr += 4;	
	}
}
/*****************************************************************************
* Function		: ExtFlash_Write_Data
* Description	: 
* Input			: 
* Output		: None
* Return		: None
* Note			: None
*****************************************************************************/
void ExFlash_Write_Data(uint32_t addr,uint8_t *pData,uint32_t len)
{
	uint32_t i;
	FLASH_SEL_CLR;
	ExtFlash_RW_Byte(0x06);					//Write Enable
	FLASH_SEL_SET;
	
	FLASH_SEL_CLR;
	ExtFlash_RW_Byte(0x02);
	ExtFlash_RW_Byte((addr >> 16) & 0xFF);
	ExtFlash_RW_Byte((addr >> 8) & 0xFF);
	ExtFlash_RW_Byte(addr & 0xFF);
	
	for(i=0;i<len;i++)
	{
		ExtFlash_RW_Byte(*(pData+i));
	}		
	FLASH_SEL_SET;
}

/*****************************************************************************
* Function		: Flash_Wt_Cmd
* Description	: 
* Input				: None
* Output			: None
* Return			: None
* Note				: None
*****************************************************************************/
void ExFlash_WaitIdle(void)
{
	uint32_t i,j;
	
	FLASH_SEL_CLR;
	for(j=0;j<500;j++)
	{
		Flash_KeyScan();
		KB_Scan();
		if((bmSendKBFlag)&&(rSys_mode == SYS_USB_MODE))
		{
			bmSendKBFlag = 0;
			USB_EPnINFunction(USB_EP1,bufKB_Usage,8);
		}
		UT_Delay_Nus(500);
		ExtFlash_RW_Byte(0x05);
		i = ExtFlash_RW_Byte(0x00);	
		if((i&0x01) == 0x00)	
			break;			
	}
	FLASH_SEL_SET;
}


